/*
 * Copyright (C) 2006 The Android Open Source Project
 * Copyright (C) 2012 YIXIA.COM

 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package cntv.player.media.widget;

import java.io.IOException;

import cntv.player.core.util.LogUtil;
import cntv.player.core.util.Utils;
import cntv.player.media.option.AvFormatOption_HttpDetectRangeSupport;
import cntv.player.media.player.IMediaPlayer;
import cntv.player.media.player.IMediaPlayer.OnCompletionListener;
import cntv.player.media.player.IMediaPlayer.OnErrorListener;
import cntv.player.media.player.IMediaPlayer.OnVideoClickListener;
import cntv.player.media.player.IMediaPlayer.OnVideoSizeChangedListener;
import cntv.player.media.player.IMediaPlayer.OnBufferingUpdateListener;
import cntv.player.media.player.IMediaPlayer.OnSlideListener;
import cntv.player.media.player.IMediaPlayer.OnInfoListener;
import cntv.player.media.player.IMediaPlayer.OnPreparedListener;
import cntv.player.media.player.IMediaPlayer.OnSeekCompleteListener;
import cntv.player.media.player.IMediaPlayer.OnSurfaceListener;
import cntv.player.media.player.KooMediaPlayer;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.media.AudioManager;
import android.net.Uri;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;

/**
 * Displays a video file. The VideoView class can load images from various
 * sources (such as resources or content providers), takes care of computing its
 * measurement from the video so that it can be used in any layout manager, and
 * provides various display options such as scaling and tinting.
 * 
 * VideoView also provide many wrapper methods for
 * {@link io.vov.vitamio.MediaPlayer}, such as {@link #getVideoWidth()},
 * {@link #setSubShown(boolean)}
 */
public class KooVideoView extends SurfaceView implements CntvPlayerControl {
    private static final String TAG = "zl";

    private Uri mUri;
    private long mDuration;

    private static final int STATE_ERROR = -1;
    private static final int STATE_IDLE = 0;
    private static final int STATE_PREPARING = 1;
    private static final int STATE_PREPARED = 2;
    private static final int STATE_PLAYING = 3;
    private static final int STATE_PAUSED = 4;
    private static final int STATE_PLAYBACK_COMPLETED = 5;
    private static final int STATE_SUSPEND = 6;
    private static final int STATE_RESUME = 7;
    private static final int STATE_SUSPEND_UNSUPPORTED = 8;

    private int mCurrentState = STATE_IDLE;
    private int mTargetState = STATE_IDLE;

    private SurfaceHolder mSurfaceHolder = null;
    protected IMediaPlayer mMediaPlayer = null;
    private KooMediaPlayer kooMediaPlayer = null;
    protected int mVideoWidth;
    protected int mVideoHeight;
    private int mVideoSarNum;
    private int mVideoSarDen;
    private int mSurfaceWidth;
    private int mSurfaceHeight;
//    private CntvController mMediaController;
    protected BaseMediaController mMediaController;
    private View mMediaBufferingIndicator;
    private OnVideoSizeChangedListener  mOnVideoSizeChangedListener;
    private OnCompletionListener mOnCompletionListener;
    private OnPreparedListener mOnPreparedListener;
    private OnErrorListener mOnErrorListener;
    private OnSeekCompleteListener mOnSeekCompleteListener;
    private OnInfoListener mOnInfoListener;
    private OnBufferingUpdateListener mOnBufferingUpdateListener;
    
    private OnSurfaceListener  mOnSurfaceListener;
    private OnVideoClickListener mOnVideoClickListener;
    private OnSlideListener mOnSlideListener;
    
    private int mCurrentBufferPercentage;
    private long mSeekWhenPrepared;
    private boolean mCanPause = true;
    private boolean mCanSeekBack = true;
    private boolean mCanSeekForward = true;
    protected Context mContext;
    
	private int mAudioSession;
	private boolean mAdPlaying;
	private boolean canSlide = true;
	
	
	protected float mAspectRatio = 0;
	protected int mVideoLayoutType = VIDEO_LAYOUT_SCALE;
	protected int videoRootWidth;
	protected int videoRootHeight;
	
	/**
	 * 播放画面原始比例
	 */
	public static final int VIDEO_LAYOUT_ORIGIN = 0;
	/**
	 * 播放画面按比例缩放，
	 * 适用于videoview首次初始化全屏，或者首次初始化半屏，以及全屏切换到半屏时画面按比例缩放
	 * 
	 */
	public static final int VIDEO_LAYOUT_SCALE = 1;
	/**
	 * 播放画面充满
	 * 适用于videoview首次初始化全屏，或者首次初始化半屏，以及全屏切换到半屏时画面充满
	 */
	public static final int VIDEO_LAYOUT_FITXY = 2;
	/**
	 * 播放画面充满，适用于全屏播放，以及半屏切换到全屏时画面充满
	 */
	public static final int VIDEO_LAYOUT_STRETCH = 3;
	/**
	 * 播放画面按比例，适用于全屏播放，以及半屏切换到全屏时画面按比例
	 */
	public static final int VIDEO_LAYOUT_ZOOM = 4;
	
	/**
	 * 视频画面原始比例
	 */
	protected float mVideoAspectRatio;
	/**
	 * videoview父视图的比例
	 */
	protected float mVideoLayoutRatio;
	
	
	
	
	private int startX;
	private int startY;
	private int moveX;
	private int moveY; 
	/**
	 * 是否滑动开始
	 */
	private boolean isSlideStart;
	/**
	 * 左右滑动时的阻力系数(较小)
	 */
	private static final float RADIO_H = 2.3f; 
	/**
	 * 上下滑动时的阻力系数(较大)
	 */
	private static final float RADIO_V = 23f; 
	/**
	 * 当滑动大于mDistanceToSlide的值时，代表滑动开始，否则视为点击
	 */
	private int mDistanceToSlide = 12;
	/**
	 * 滑动方向，左、右、上、下
	 */
	private int slideState = IMediaPlayer.SLIDE_STATE_NONE;
	/**
	 * 滑动方向，横向、竖向
	 */
	private int currentSlideState = IMediaPlayer.SLIDE_STATE_NONE;
	/**
	 * 横向移动距离
	 */
	private int distanceH = 0;
	/**
	 * 竖向移动距离
	 */
	private int distanceV = 0;

    public KooVideoView(Context context) {
        super(context);
        initVideoView(context);
    }

    public KooVideoView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
        initVideoView(context);
    }

    public KooVideoView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initVideoView(context);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = getDefaultSize(mVideoWidth, widthMeasureSpec);
        int height = getDefaultSize(mVideoHeight, heightMeasureSpec);
        setMeasuredDimension(width, height);
    }
    
	/**
	 * Set the display options
	 * 
	 * @param layoutType
	 *            <ul>
	 *            <li>{@link #VIDEO_LAYOUT_ORIGIN}
	 *            <li>{@link #VIDEO_LAYOUT_SCALE}
	 *            <li>{@link #VIDEO_LAYOUT_STRETCH}
	 *            <li>{@link #VIDEO_LAYOUT_ZOOM}
	 *            <li>{@link #VIDEO_LAYOUT_FITXY}
	 *            </ul>
	 */
    public void setVideoLayout(int layoutType) {
    	mVideoLayoutType = layoutType;
		mAspectRatio = mVideoLayoutRatio;
    	
    	int windowWidth = Utils.screenWidth(mContext);
		int windowHeight = Utils.screenHeight(mContext);
		float mWindowRatio = windowWidth / (float)windowHeight;
		mVideoAspectRatio = getVideoAspectRatio();
		mVideoLayoutRatio = getVideoLayoutRatio();
//		LogUtil.e("zl", "VideoView setVideoLayout() mVideoAspectRatio = " + mVideoAspectRatio);
//		LogUtil.e("zl", "VideoView setVideoLayout() mVideoLayoutRatio = " + mVideoLayoutRatio);
		if(mVideoAspectRatio == 0){
			return;
		}
		LayoutParams lp = getLayoutParams();
		switch (layoutType) {
		case VIDEO_LAYOUT_ORIGIN://原始比例
			lp.width = mVideoWidth; 
			lp.height = mVideoHeight;
			break;
		case VIDEO_LAYOUT_SCALE://按比例缩放
			lp.width = mVideoLayoutRatio > mVideoAspectRatio ? (int) (videoRootHeight*mVideoAspectRatio) : videoRootWidth;
			lp.height = mVideoLayoutRatio > mVideoAspectRatio ? videoRootHeight : (int) (videoRootWidth/mVideoAspectRatio); 
			break;
		case VIDEO_LAYOUT_STRETCH://全屏充满
			LogUtil.e("zl", "VideoView setVideoLayout VIDEO_LAYOUT_STRETCH mWindowRatio = " + mWindowRatio);
			lp.width = windowWidth;
			lp.height = windowHeight;
			break;
		case VIDEO_LAYOUT_ZOOM://全屏按比例
			LogUtil.e("zl", "VideoView setVideoLayout VIDEO_LAYOUT_ZOOM mWindowRatio = " + mWindowRatio);
			
			lp.width = mWindowRatio > mVideoAspectRatio ? (int) (windowHeight*mVideoAspectRatio) : windowWidth;
			lp.height = mWindowRatio > mVideoAspectRatio ? windowHeight : (int) (windowWidth/mVideoAspectRatio);
			
			LogUtil.e("zl", "VideoView setVideoLayout VIDEO_LAYOUT_ZOOM lp.width = " + lp.width);
			LogUtil.e("zl", "VideoView setVideoLayout VIDEO_LAYOUT_ZOOM lp.height = " + lp.height);
			break;
		case VIDEO_LAYOUT_FITXY://画面充满，也适用于全屏充满
			lp.width = LayoutParams.MATCH_PARENT; 
			lp.height = LayoutParams.MATCH_PARENT;
			break;

		default:
			break;
		}
    	setLayoutParams(lp);
    	getHolder().setFixedSize(mVideoWidth, mVideoHeight);
    	requestLayout();
    	invalidate();
    }
    
    public int getVideoLayoutType(int layoutType,int layoutRatio){
    	return mVideoLayoutType;
    }
    
    /**
     * 获取视频videoview布局 的父view的宽高比
     * @return
     */
    protected float getVideoLayoutRatio(){
    	if(mVideoLayoutRatio != 0){
     		return mVideoLayoutRatio;
     	}
    	 ViewGroup anchorView = null;
         if(this.getParent() instanceof ViewGroup){
         	anchorView = (ViewGroup)(this.getParent());
         	videoRootWidth = anchorView.getWidth(); 
         	videoRootHeight = anchorView.getHeight();
         	if(videoRootWidth != 0 && videoRootHeight != 0){
         		return videoRootWidth / (float)videoRootHeight;
         	}
         }
		return mVideoAspectRatio;
    }
    
    /**
     * 获取视频原始画面比例(宽高比)
     * @return
     */
    public float getVideoAspectRatio(){
    	if(kooMediaPlayer != null){
    		return kooMediaPlayer.getVideoAspectRatio();
    	}else if(mVideoWidth != 0 && mVideoHeight != 0){
    		return mVideoWidth / (float)mVideoHeight;
    	}else{
    		return 0;
    	}
    }
    
    

    private void initVideoView(Context ctx) {
        mContext = ctx;
        mVideoWidth = 0;
        mVideoHeight = 0;
        mVideoSarNum = 0;
        mVideoSarDen = 0;
        getHolder().addCallback(mSHCallback);
        setFocusable(true);
        setFocusableInTouchMode(true);
        requestFocus();
        mCurrentState = STATE_IDLE;
        mTargetState = STATE_IDLE; 
//        mDistanceToSlide = getResources().getDimensionPixelOffset(R.dimen.distance_call_to_slide);
        if (ctx instanceof Activity){
            ((Activity) ctx).setVolumeControlStream(AudioManager.STREAM_MUSIC);
        }
    }

    public boolean isValid() {
        return (mSurfaceHolder != null && mSurfaceHolder.getSurface().isValid());
    }

    public void setVideoPath(String path) {
        setVideoURI(Uri.parse(path));
    }

    public void setVideoURI(Uri uri) {
        mUri = uri;
        mSeekWhenPrepared = 0;
        openVideo();
        requestLayout();
        invalidate();
    }

    public void stopPlayback() {
        if (mMediaPlayer != null) {
            mMediaPlayer.stop();
            mMediaPlayer.release();
            mMediaPlayer = null;
            kooMediaPlayer = null;
            mCurrentState = STATE_IDLE;
            mTargetState = STATE_IDLE;
        }
        if(mMediaController != null){
        	mMediaController.initialize();
        	mMediaController.setMediaPlayer(null);
        }
    }

    private void openVideo() {
        if (mUri == null || mSurfaceHolder == null)
            return;

        Intent i = new Intent("com.android.music.musicservicecommand");
        i.putExtra("command", "pause");
        mContext.sendBroadcast(i);

        release(false);
        try {
            mDuration = -1;
            mCurrentBufferPercentage = 0;
            // mMediaPlayer = new AndroidMediaPlayer();
            kooMediaPlayer = null;
            if (mUri != null) {
                kooMediaPlayer = new KooMediaPlayer();
                ((KooMediaPlayer) kooMediaPlayer)
                        .setAvOption(AvFormatOption_HttpDetectRangeSupport.Disable);
            }
            mMediaPlayer = kooMediaPlayer;
            mMediaPlayer.setOnPreparedListener(mPreparedListener);
            mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener);
            mMediaPlayer.setOnCompletionListener(mCompletionListener);
            mMediaPlayer.setOnErrorListener(mErrorListener);
            mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener);
            mMediaPlayer.setOnInfoListener(mInfoListener);
            mMediaPlayer.setOnSeekCompleteListener(mSeekCompleteListener);
            if (mUri != null)
                mMediaPlayer.setDataSource(mUri.toString());
            mMediaPlayer.setDisplay(mSurfaceHolder);
            mMediaPlayer.setScreenOnWhilePlaying(true);
            mMediaPlayer.prepareAsync();
            mCurrentState = STATE_PREPARING;
            attachMediaController();
        } catch (IOException ex) {
        	ex.printStackTrace();
            LogUtil.e(TAG, "Unable to open content: " + mUri);
            mCurrentState = STATE_ERROR;
            mTargetState = STATE_ERROR;
            mErrorListener.onError(mMediaPlayer,
                    IMediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
            return;
        } catch (IllegalArgumentException ex) {
        	ex.printStackTrace();
            LogUtil.e(TAG, "Unable to open content: " + mUri);
            mCurrentState = STATE_ERROR;
            mTargetState = STATE_ERROR;
            mErrorListener.onError(mMediaPlayer,
                    IMediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
            return;
        }
    }

    public void setMediaController(BaseMediaController controller) {
        if (mMediaController != null)
            mMediaController.hide();
        mMediaController = controller;
        attachMediaController();
    }

    public void setMediaBufferingIndicator(View mediaBufferingIndicator) {
        if (mMediaBufferingIndicator != null)
            mMediaBufferingIndicator.setVisibility(View.GONE);
        mMediaBufferingIndicator = mediaBufferingIndicator;
    }

    private void attachMediaController() {
        if (mMediaPlayer != null && mMediaController != null) {
        	 mMediaController.setMediaPlayer(this);
             ViewGroup anchorView = null;
             if(this.getParent() instanceof ViewGroup){
             	anchorView = (ViewGroup)(this.getParent());
             	anchorView.setOnTouchListener(mOnTouchListener);
             }else{
             	//可以抛出异常
             }
             mMediaController.setAnchorView(anchorView);
             mMediaController.setEnabled(isInPlaybackState());
        }
    }

    OnVideoSizeChangedListener mSizeChangedListener = new OnVideoSizeChangedListener() {
        public void onVideoSizeChanged(IMediaPlayer mp, int width, int height, int sarNum, int sarDen) {
        	
//			LogUtil.e(TAG, "KooVideoView onVideoSizeChanged: width = " + width + ",height = " + height);// width 和height不准确
//        	LogUtil.e(TAG, "KooVideoView onVideoSizeChanged: sarNum = " + sarNum + ",sarDen = " + sarDen);
			int videoWidth = mp.getVideoWidth();
			int videoHeight = mp.getVideoHeight();
			mVideoSarNum = sarNum;
			mVideoSarDen = sarDen;
			boolean isVideoSizeChanged = (videoWidth != mVideoWidth || videoHeight != mVideoHeight);
			if (videoWidth != 0 && videoHeight != 0 && isVideoSizeChanged) {
				LogUtil.e(TAG, "KooVideoView onVideoSizeChanged: videoWidth = " + videoWidth + ",videoHeight = " + videoHeight);
				if (mOnVideoSizeChangedListener != null) {
					mOnVideoSizeChangedListener.onVideoSizeChanged(mp, width, height, sarNum, sarDen);
				}
				mVideoWidth = videoWidth;
				mVideoHeight = videoHeight;
				setVideoLayout(mAdPlaying ? VIDEO_LAYOUT_FITXY : mVideoLayoutType);
			}
		}
    };

    OnPreparedListener mPreparedListener = new OnPreparedListener() {
        public void onPrepared(IMediaPlayer mp) {
            LogUtil.d(TAG, "onPrepared");
            mCurrentState = STATE_PREPARED;
            mTargetState = STATE_PLAYING;

            if (mOnPreparedListener != null)
                mOnPreparedListener.onPrepared(mMediaPlayer);
            if (mMediaController != null)
                mMediaController.setEnabled(true);
            mVideoWidth = mp.getVideoWidth();
            mVideoHeight = mp.getVideoHeight();
//            LogUtil.e(TAG, "KooVideoView onPrepared: mVideoWidth = " + mVideoWidth + ",mVideoHeight = " + mVideoHeight);

            long seekToPosition = mSeekWhenPrepared;

            if (seekToPosition != 0)
                seekTo(seekToPosition);
            if (mVideoWidth != 0 && mVideoHeight != 0) {
//                setVideoLayout(mVideoLayoutType);
                setVideoLayout(mAdPlaying ? VIDEO_LAYOUT_FITXY : mVideoLayoutType);
                if (mSurfaceWidth == mVideoWidth
                        && mSurfaceHeight == mVideoHeight) {
                    if (mTargetState == STATE_PLAYING) {
                        start();
                        if (mMediaController != null)
                            mMediaController.show();
                    } else if (!isPlaying()
                            && (seekToPosition != 0 || getCurrentPosition() > 0)) {
                        if (mMediaController != null)
                            mMediaController.show(0);
                    }
                }
            } else if (mTargetState == STATE_PLAYING) {
                start();
            }
        }
    };

    private OnCompletionListener mCompletionListener = new OnCompletionListener() {
        public void onCompletion(IMediaPlayer mp) {
            LogUtil.d(TAG, "onCompletion");
            mCurrentState = STATE_PLAYBACK_COMPLETED;
            mTargetState = STATE_PLAYBACK_COMPLETED;
            if (mMediaController != null)
                mMediaController.hide();
            if (mOnCompletionListener != null)
                mOnCompletionListener.onCompletion(mMediaPlayer);
        }
    };

    private OnErrorListener mErrorListener = new OnErrorListener() {
        public boolean onError(IMediaPlayer mp, int framework_err, int impl_err) {
            mCurrentState = STATE_ERROR;
            mTargetState = STATE_ERROR;
            if (mMediaController != null)
                mMediaController.hide();

            if (mOnErrorListener != null) {
                if (mOnErrorListener.onError(mMediaPlayer, framework_err, impl_err))
                    return true;
            }

            /*if (getWindowToken() != null) {
                int message = framework_err == IMediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK ? R.string.videoview_error_text_invalid_progressive_playback
                        : R.string.videoview_error_text_unknown;

                new AlertDialog.Builder(mContext)
                        .setTitle(R.string.videoview_error_title)
                        .setMessage(message)
                        .setPositiveButton(
                                R.string.videoview_error_button,
                                new DialogInterface.OnClickListener() {
                                    public void onClick(DialogInterface dialog,
                                            int whichButton) {
                                        if (mOnCompletionListener != null)
                                            mOnCompletionListener
                                                    .onCompletion(mMediaPlayer);
                                    }
                                }).setCancelable(false).show();
            }*/
            return true;
        }
    };

    private OnBufferingUpdateListener mBufferingUpdateListener = new OnBufferingUpdateListener() {
        public void onBufferingUpdate(IMediaPlayer mp, int percent) {
            mCurrentBufferPercentage = percent;
            if (mOnBufferingUpdateListener != null)
                mOnBufferingUpdateListener.onBufferingUpdate(mp, percent);
        }
    };

    private OnInfoListener mInfoListener = new OnInfoListener() {
        @Override
        public boolean onInfo(IMediaPlayer mp, int what, int extra) {
            if (mOnInfoListener != null) {
                mOnInfoListener.onInfo(mp, what, extra);
            } else if (mMediaPlayer != null) {
                if (what == IMediaPlayer.MEDIA_INFO_BUFFERING_START) {
                    LogUtil.i(TAG, "onInfo: (MEDIA_INFO_BUFFERING_START)");
                    if (mMediaBufferingIndicator != null)
                        mMediaBufferingIndicator.setVisibility(View.VISIBLE);
                } else if (what == IMediaPlayer.MEDIA_INFO_BUFFERING_END) {
                    LogUtil.i(TAG, "onInfo: (MEDIA_INFO_BUFFERING_END)");
                    if (mMediaBufferingIndicator != null)
                        mMediaBufferingIndicator.setVisibility(View.GONE);
                }
            }

            return true;
        }
    };

    private OnSeekCompleteListener mSeekCompleteListener = new OnSeekCompleteListener() {
        @Override
        public void onSeekComplete(IMediaPlayer mp) {
            LogUtil.d(TAG, "onSeekComplete");
            if (mOnSeekCompleteListener != null)
                mOnSeekCompleteListener.onSeekComplete(mp);
        }
    };

    public void setOnPreparedListener(OnPreparedListener l) {
        mOnPreparedListener = l;
    }

    public void setOnCompletionListener(OnCompletionListener l) {
        mOnCompletionListener = l;
    }

    public void setOnErrorListener(OnErrorListener l) {
        mOnErrorListener = l;
    }

    public void setOnBufferingUpdateListener(OnBufferingUpdateListener l) {
        mOnBufferingUpdateListener = l;
    }

    public void setOnSeekCompleteListener(OnSeekCompleteListener l) {
        mOnSeekCompleteListener = l;
    }

    public void setOnInfoListener(OnInfoListener l) {
        mOnInfoListener = l;
    }
    
    public void setOnVideoSizeChangedListener(OnVideoSizeChangedListener l) {
		mOnVideoSizeChangedListener = l;
	}
    
    public void setOnSurfaceListener(OnSurfaceListener l) {
		this.mOnSurfaceListener = l;
	}
    public void setOnSlideListener(OnSlideListener l) {
		this.mOnSlideListener = l;
	}
    
	SurfaceHolder.Callback mSHCallback = new SurfaceHolder.Callback() {
    	
        public void surfaceChanged(SurfaceHolder holder, int format,int w, int h){
//        	LogUtil.i("zl","SurfaceHolder.Callback surfaceChanged");
            mSurfaceWidth = w;
            mSurfaceHeight = h;
            LogUtil.e("zl","surfaceChanged() mSurfaceWidth = " + mSurfaceWidth + ",mSurfaceHeight = " + mSurfaceHeight);
            boolean isValidState =  (mTargetState == STATE_PLAYING);
            boolean hasValidSize = (mVideoWidth == w && mVideoHeight == h);
            if (mMediaPlayer != null && isValidState && hasValidSize) {
                if (mSeekWhenPrepared != 0) {
                    seekTo(mSeekWhenPrepared);
                }
                start();
            }
        }

		public void surfaceCreated(SurfaceHolder holder) {
//			LogUtil.i("zl","SurfaceHolder.Callback surfaceCreated");
			mSurfaceHolder = holder;
			if(mOnSurfaceListener != null){
				mOnSurfaceListener.onSurfaceCreate();
			}else if (mMediaPlayer != null && mCurrentState == STATE_SUSPEND
                    && mTargetState == STATE_RESUME) {
                mMediaPlayer.setDisplay(mSurfaceHolder);
                resume();
            } else {
                openVideo();
            }
			
		}

		public void surfaceDestroyed(SurfaceHolder holder) {
			// after we return from this we can't use the surface any more
//			LogUtil.i("zl","SurfaceHolder.Callback surfaceDestroyed");
			// if (mMediaController != null) mMediaController.hide();
			mSurfaceHolder = null;
			if(mOnSurfaceListener != null){
				mOnSurfaceListener.onSurfaceDestroyed();
			}else{
				release(true);
			}
		}
	};

    private void release(boolean cleartargetstate) {
        if (mMediaPlayer != null) {
            mMediaPlayer.reset();
            mMediaPlayer.release();
            mMediaPlayer = null;
            mCurrentState = STATE_IDLE;
            if (cleartargetstate)
                mTargetState = STATE_IDLE;
        }
    }
    
    public void setOnVideoClickListener(OnVideoClickListener l){
    	this.mOnVideoClickListener = l;
    	
    }
    
    OnClickListener mOnClickListener = new OnClickListener() {
		
		@Override
		public void onClick(View v) {
			// TODO Auto-generated method stub
			
		}
	};
    
    
    OnTouchListener mOnTouchListener = new OnTouchListener() {
		
		@Override
		public boolean onTouch(View v, MotionEvent ev) {
			// TODO Auto-generated method stub
			if(mMediaPlayer == null){
				return false;
			}
			if (mMediaController == null && mOnVideoClickListener != null) {
	    		mOnVideoClickListener.onVideoClick();
	        	return false;
	        }else if(mOnSlideListener == null || !canSlide){
	        	toggleMediaControlsVisiblity();
	        	return false;
	        }else{
	        	switch (ev.getAction()) {
	    		case MotionEvent.ACTION_DOWN:
//	    			LogUtil.i("zl", "MotionEvent.ACTION_DOWN");
	    			startX = (int)ev.getX();
	    			startY = (int) ev.getY();
	    			
	    			break;
	    		case MotionEvent.ACTION_MOVE:
//	    			LogUtil.i("zl", "MotionEvent.ACTION_MOVE");
	    			moveX = (int) ev.getX();
	    			moveY = (int) ev.getY(); 
	    			
	    			// 当前触摸的点到上一个触摸点的位移
	    			int diffX = moveX - startX;
	    			int diffY = moveY - startY;
	    			
	    			if(Math.abs(diffY) < Math.abs(diffX) && Math.abs(diffX)>=mDistanceToSlide){//代表左右滑动
	    				
	    				if(currentSlideState != IMediaPlayer.SLIDE_STATE_VERTICAL){//防止横向滑动的时候未松手又纵向滑动
	    					currentSlideState = IMediaPlayer.SLIDE_STATE_HORIZONRAL;
	    					slideState = diffX>0 ? IMediaPlayer.SLIDE_STATE_RIGHT : IMediaPlayer.SLIDE_STATE_LEFT;
	    					diffX /= RADIO_H;
	        				if(!isSlideStart){
	        					isSlideStart = true;
	        					mOnSlideListener.onSlideStart(slideState);
	        				}
	        				if(diffX != distanceH){
	        					distanceH = diffX;
	        					mOnSlideListener.onSliding(slideState, distanceH);
	        				}
	    				}
	    				
	    			}else if(Math.abs(diffY) > Math.abs(diffX) && Math.abs(diffY)>=mDistanceToSlide){//代表上下滑动
	    				if(currentSlideState != IMediaPlayer.SLIDE_STATE_HORIZONRAL){//防止纵向滑动的时候未松手又横向滑动
	    					currentSlideState = IMediaPlayer.SLIDE_STATE_VERTICAL;
	    					slideState = diffY>0 ? IMediaPlayer.SLIDE_STATE_DOWN : IMediaPlayer.SLIDE_STATE_UP;
	    					diffY /= RADIO_V;
	    					
	        				if(!isSlideStart){
	        					isSlideStart = true;
	        					mOnSlideListener.onSlideStart(slideState);
	        				}
	        				if(diffY != distanceV){
	        					distanceV = diffY;
	        					mOnSlideListener.onSliding(slideState, distanceV);
	        				}
	    				}
	    			}
	    			break;
	    		case MotionEvent.ACTION_UP:
//	    			LogUtil.i("zl", "MotionEvent.ACTION_UP");
	    			moveX = (int) ev.getX();
	    			moveY = (int) ev.getY(); 
	    			
	    			isSlideStart = false;
					if (currentSlideState == IMediaPlayer.SLIDE_STATE_HORIZONRAL) {
						mOnSlideListener.onSlideEnd(slideState, distanceH);
						distanceH = 0;
						slideState = IMediaPlayer.SLIDE_STATE_NONE;
						currentSlideState = IMediaPlayer.SLIDE_STATE_NONE;
					} else if (currentSlideState == IMediaPlayer.SLIDE_STATE_VERTICAL) {
						mOnSlideListener.onSlideEnd(slideState, distanceV);
						distanceV = 0;
						slideState = IMediaPlayer.SLIDE_STATE_NONE;
						currentSlideState = IMediaPlayer.SLIDE_STATE_NONE;
					} else if(mMediaController != null){
						toggleMediaControlsVisiblity();
					}
	    			break;
	    		case MotionEvent.ACTION_CANCEL:
	    			LogUtil.i("zl", "MotionEvent.ACTION_CANCEL");
	    			slideState = IMediaPlayer.SLIDE_STATE_NONE;
	    			currentSlideState = IMediaPlayer.SLIDE_STATE_NONE;
	    			mOnSlideListener.onSlideEnd(slideState, 0);
					distanceV = 0;
					distanceH = 0;
	    			
	    			break;
	    		default:
	    			break;
	    		}
	        	return true;
	        }
		}
	};
    
    @Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		return super.onTouchEvent(event);
	}

	@Override
    public boolean onTrackballEvent(MotionEvent ev) {
        if (isInPlaybackState() && mMediaController != null)
            toggleMediaControlsVisiblity();
        return false;
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
    	return onKey(keyCode,event);
       //return super.onKeyDown(keyCode, event);
    }
    
    protected boolean onKey(int keyCode, KeyEvent event) {
        boolean isKeyCodeSupported = keyCode != KeyEvent.KEYCODE_BACK
                && keyCode != KeyEvent.KEYCODE_VOLUME_UP
                && keyCode != KeyEvent.KEYCODE_VOLUME_DOWN
                && keyCode != KeyEvent.KEYCODE_MENU
                && keyCode != KeyEvent.KEYCODE_CALL
                && keyCode != KeyEvent.KEYCODE_ENDCALL;
        if (isInPlaybackState() && isKeyCodeSupported
                && mMediaController != null) {
            if (keyCode == KeyEvent.KEYCODE_HEADSETHOOK
                    || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE
                    || keyCode == KeyEvent.KEYCODE_SPACE) {
                if (mMediaPlayer.isPlaying()) {
                    pause();
                    mMediaController.show();
                } else {
                    start();
                    mMediaController.hide();
                }
                return true;
            } else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP
                    && mMediaPlayer.isPlaying()) {
                pause();
                mMediaController.show();
            } else {
                toggleMediaControlsVisiblity();
            }
        }
        return super.onKeyDown(keyCode, event);
	}

    private void toggleMediaControlsVisiblity() {
    	if(mMediaController==null){
    		return;
    	}
        if (mMediaController.isShowing()) {
            mMediaController.hide();
        } else {
            mMediaController.show();
            
        }
    }

    @Override
    public void start() {
        if (isInPlaybackState()) {
            mMediaPlayer.start();
            mCurrentState = STATE_PLAYING;
        }
        mTargetState = STATE_PLAYING;
    }

    @Override
    public void pause() {
        if (isInPlaybackState()) {
            if (mMediaPlayer.isPlaying()) {
                mMediaPlayer.pause();
                mCurrentState = STATE_PAUSED;
            }
        }
        mTargetState = STATE_PAUSED;
    }

    public void resume() {
        if (mSurfaceHolder == null && mCurrentState == STATE_SUSPEND) {
            mTargetState = STATE_RESUME;
        } else if (mCurrentState == STATE_SUSPEND_UNSUPPORTED) {
            openVideo();
        }
    }

    @Override
    public long getDuration() {
        if (isInPlaybackState()) {
            if (mDuration > 0)
                return (int) mDuration;
            mDuration = mMediaPlayer.getDuration();
            return (int) mDuration;
        }
        mDuration = -1;
        return mDuration;
    }

    @Override
    public long getCurrentPosition() {
        if (isInPlaybackState()) {
            long position = mMediaPlayer.getCurrentPosition();
            LogUtil.i("kooMEDIA", "KooVideoView position = " + position);
            return position;
        }
        return 0;
    }

    @Override
    public void seekTo(long msec) {
        if (isInPlaybackState()) {
        	if(mMediaController != null){
        		mMediaController.setSeekComplete(false);
        	}
            mMediaPlayer.seekTo(msec);
            mSeekWhenPrepared = 0;
        } else {
            mSeekWhenPrepared = msec;
        }
    }

    @Override
    public boolean isPlaying() {
        return isInPlaybackState() && mMediaPlayer.isPlaying();
    }

    @Override
    public int getBufferPercentage() {
        if (mMediaPlayer != null)
            return mCurrentBufferPercentage;
        return 0;
    }

    public int getVideoWidth() {
        return mVideoWidth;
    }

    public int getVideoHeight() {
        return mVideoHeight;
    }

    protected boolean isInPlaybackState() {
        return (mMediaPlayer != null && mCurrentState != STATE_ERROR
                && mCurrentState != STATE_IDLE && mCurrentState != STATE_PREPARING);
    }

    public boolean canPause() {
        return mCanPause;
    }

    public boolean canSeekBackward() {
        return mCanSeekBack;
    }

    public boolean canSeekForward() {
        return mCanSeekForward;
    }
    
    @Override
    public int getAudioSessionId() {
        return mAudioSession;
    }

    /**
     * 设置是否播放广告，true 代表此videoview播放的广告，播放画面一律充满
     * @param adPlaying
     */
    public void setAdPlaying(boolean adPlaying){ 
    	mAdPlaying = adPlaying;
    }
    
	@Override
	public boolean isAdPlaying() {
		// TODO Auto-generated method stub
		return mAdPlaying;
	}
	
	public void canSlide(boolean canSlide){
		this.canSlide = canSlide;
	}
}
